package com.chen.tliaswebtest.aspect;

import com.chen.tliaswebtest.pojo.OperateLog;
import com.chen.tliaswebtest.service.OperationService;
import com.chen.tliaswebtest.utils.CurrentHolderUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * @author chen
 * @version 1.0
 * @create_date 2025/7/26
 * 日志操作拦截切面
 */
@Slf4j
@Aspect
@Component
public class OperationLogAspect {
    private final OperationService operationService;

    public OperationLogAspect(OperationService operationService) {
        this.operationService = operationService;
    }

    @Pointcut("@annotation(com.chen.tliaswebtest.annotation.LogOperation)")
    private void log() {
    }

    // 围绕通知方法
    @Around("log()")
    public Object addLog(ProceedingJoinPoint point) throws Throwable {
        long start = System.currentTimeMillis();
        // 执行方法
        Object result = point.proceed();
        long end = System.currentTimeMillis();
        // 计算耗时
        long costTime = end - start;
        // 添加日志
        addLog(point, result.toString(), null, costTime);
        return result;
    }

    // 异常后通知ff
    @AfterThrowing(value = "log()", throwing = "e")
    public Exception afterThrowing(JoinPoint joinPoint, Exception e) {
        addLog(joinPoint, e.getMessage(), e.getMessage(), 0L);
        return e;
    }

    // 添加操作日志，无论是否有异常
    private void addLog(JoinPoint joinPoint, String result, String message, Long costTime) {
        // 创建日志实体类对象
        OperateLog operateLog = OperateLog.builder()
                // 获取当前用户id
                .operateEmpId(CurrentHolderUtils.getCurrentId())
                // 获取当前时间
                .operateTime(LocalDateTime.now())
                // 获取当前类名
                .className(joinPoint.getTarget().getClass().getName())
                // 获取当前方法名
                .methodName(joinPoint.getSignature().getName())
                // 获取参数
                .methodParams(Arrays.toString(joinPoint.getArgs()))
                // 获取返回值
                .returnValue(result)
                // 异常原因
                .exception(message)
                // 获取耗时
                .costTime(costTime)
                .build();
        // 添加日志
        operationService.addLog(operateLog);
    }
}
